package state

import (
	"fmt"
	"iot-base/common/cache"
	"iot-base/common/config"
	"iot-base/common/event"
	"iot-base/common/eventtype"

	//"iot-base/common/notify"
	rc "iot-base/common/redis"
	//"sync"
	"time"
)

func offlineAlarm(tid string, time int64) {

	var alarm eventtype.Alarm
	alarm.TID = tid
	alarm.AlarmID = "offline"
	alarm.Time = time
	alarm.Flag = "BEGIN"
	alarm.Checker = "onlineChecker"
	event.ThingAlarm(&alarm)

}

func clearOfflineAlarm(tid string, time int64) {

	var alarm eventtype.Alarm
	alarm.TID = tid
	alarm.AlarmID = "offline"
	alarm.ClearTime = time
	alarm.Flag = "END"
	alarm.Checker = "onlineChecker"
	event.ThingAlarmClear(&alarm)

}

//var mapNotToCheck sync.Map

func checkState() {
	//fmt.Println("checkstate----------------")
	tnow := time.Now()
	now := tnow.Unix()
	paths, _ := rc.SMembers("notCheckOnline.path.").Result()
	//now := time.Now().Unix()
	cache.ScanIDs(100, func(id string) {
		//fmt.Println("checkstate----------------", id)
		//thingid := "thing." + id + ".state"
		//var info onlineInfo
		if id == config.SelfOption.ID {
			cache.SetLastAliveTime(id, now)
			cache.SetThingState(id, "online", tnow)
			return
		}
		pInfo, err := cache.GetThing(id)

		if pInfo == nil || pInfo.Thing.IsStation || err != nil {
			return
		}
		if pInfo.Thing.StatusUsed != 1 {
			return
		}
		for _, path := range paths {
			if path == pInfo.Thing.ProtocolPath {
				return
			}
		}
		var isProxyOnCloud = false
		//一个默认的设备不是代理，也没有配置代理设备，因而isProxyCloud为false，相当于平台直连

		if config.PType == "cloud" {
			if !pInfo.Thing.IsProxy && pInfo.Thing.ProxyThingID != "" {
				//id = pInfo.Thing.ProxyThingID
				isProxyOnCloud = true
			} else { //不是自身管理的设备
				if !pInfo.Thing.IsProxy || pInfo.Thing.ProxyThingID != "" { //不是边缘计算节点，则不再判断是否在线
					return
				}
			}
		} else { //在边缘侧
			//不是自己管理的设备不判断设备状态
			if pInfo.Thing.ProxyThingID != config.SelfOption.ID {
				fmt.Println("cfg error----------proxythingid not selfid--", pInfo.Thing.ProxyThingID, config.SelfOption.ID)
				return
			}

		}
		var lastTime int64
		var errGet error
		if isProxyOnCloud {
			lastTime, errGet = cache.GetLastAliveTime(pInfo.Thing.ProxyThingID)
		} else {
			lastTime, errGet = cache.GetLastAliveTime(id)
		}

		//fmt.Println("hmget ", cmd)
		if errGet != nil {
			//fmt.Println("------------check device offline---------", id, errGet)
			cache.SetThingState(id, "offline", tnow)
			offlineAlarm(id, now)
		} else {
			if now-lastTime > 200 { //心跳3分钟没有信息，则断线
				//fmt.Println("------------check device offline----2-----", id, now-lastTime)
				cache.SetThingState(id, "offline", tnow)
				offlineAlarm(id, now)
			} else if !isProxyOnCloud { //当前在线,在云端被代理设备不做告警消除
				cache.SetThingState(id, "online", tnow)
				clearOfflineAlarm(id, now)
			}
		}
		//fmt.Println("info:", info)

	})
}

func init() {
	//checkState()
	go func() {
		//time.Sleep(time.Duration(90) * time.Second) //启动后等待90秒，等待设备上线
		timeout := 20
		ticker := time.NewTicker(time.Duration(timeout) * time.Second)
		locker := cache.CreateLocker()
		clearOfflineAlarm(config.SelfOption.ID, time.Now().Unix())
		//存储到thing.thingid.state，应使用分布式锁
		for range ticker.C {
			isOK := locker.TryLock(timeout - 2)
			if isOK {
				checkState()
				locker.UnLock()
			}

		}
	}()

}
